#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/timerfd.h>

int main()
{
    // 1,创建定时器文件描述符：
    int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
    if (timerfd < 0)
    {
        perror("timerfd_create error");
        return -1;
    }

    // struct itimerspec
    // {
    //     struct timespec it_interval; // 后续周期性超时的间隔
    //     struct timespec it_value;    // 首次超时的时间
    // };

    // struct timespec
    // {
    //     time_t tv_sec; // 秒
    //     long tv_nsec;  // 纳秒
    // };


    // 2,设置定时器参数
    struct itimerspec itime;
    itime.it_value.tv_sec = 1;   // 首次超时时间为1秒后
    itime.it_value.tv_nsec = 0;   
    itime.it_interval.tv_sec = 1; //后续周期性超时的间隔
    itime.it_interval.tv_nsec = 0;//第一次超时后，每次超时的间隔时
    
        //    int timerfd_settime(int fd, int flags,
        //                    const struct itimerspec *new_value,
        //                    struct itimerspec *_Nullable old_value);

        // flags : 控制时间解释方式的标志，支持以下值：
        // 0, new_value 为相对时间，
        // TFD_TIMER_ABSTIME：new_value 中的时间是绝对时间（基于 CLOCK_MONOTONIC 时钟）。

    timerfd_settime(timerfd, 0, &itime, NULL);

    while(1)
    {
        uint64_t times;
        int ret = read(timerfd, &times, 8);
        
        // read() 的第三个参数 8 代表读取的字节数，这是因为：
        // uint64_t 类型在内存中占 8 字节（64 位）。
        // timerfd 的内核计数器是一个 uint64_t 值。
        // 必须读取完整的 8 字节，否则 read() 会失败（返回 -1，errno 为 EINVAL）。

        // 当定时器超时时，read() 返回，times 表示自上次读取以来发生的超时次数。
        if(ret < 0)
        {
            perror("read error");
            return -1;
        }

        printf("超时了， 距离上一次超时了%ld\n", times);
        // 每次超时事件发生后，timerfd 变为可读状态，read() 会将计数器重置为 0。因此，下一次超时前计数器最多为 1。
    }
    
    close(timerfd);
    return 0;
}
